package com.audaque.springboot.foshanupload.web.esdatademo.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.audaque.springboot.foshanupload.web.esdatademo.model.pojo.Blog;
import com.audaque.springboot.foshanupload.web.esdatademo.model.pojo.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.flush.FlushRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.*;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Cancellable;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

import static org.elasticsearch.common.unit.TimeValue.timeValueMillis;

/**
 * @author zgb
 * @desc ...
 * @date 2023-06-12 20:43:09
 */
@Slf4j
@Api(tags = "增删改查（文档）")
@RestController
@RequestMapping("restHighLevelClientDoc")
public class RestHighLevelClientDocController {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @ApiOperation("排序查询文档")
    @GetMapping("sort")
    public List<Blog> sort() throws Exception {
        List<Blog> blogs = new ArrayList<>();
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().sort("serialNum", SortOrder.DESC);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;

    }

    @ApiOperation("嵌套查询文档")
    @GetMapping("nested")
    public String nested() throws Exception {
        String result = null;
        SearchRequest searchRequest = new SearchRequest("user");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.nestedQuery("children", QueryBuilders.boolQuery().must(QueryBuilders.matchQuery("children.first", "John")).must(QueryBuilders.matchQuery("children.second", "Smith")), ScoreMode.None));
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            SearchHit at = searchHits.getAt(0);
            result = at.getSourceAsString();
        } else {
            throw new Exception("es运行异常");
        }

        return result;

    }

    @ApiOperation("返回指定字段查询文档")
    @GetMapping("specCol")
    public String specCol() throws Exception {
        String result = null;
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.termQuery("serialNum", "1"))
                //设置fetchSource参数，传入两个数组，前一个是包含的字段，后一个是排除的字段
                .fetchSource(new String[]{"serialNum"}, new String[]{});
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            SearchHit at = searchHits.getAt(0);
            result = at.getSourceAsString();
        } else {
            throw new Exception("es运行异常");
        }

        return result;

    }


    /**
     * 这种常用于根据筛选条件之后抽取全部数据的场景，
     * scroll API 可以被用来检索大量的结果， 甚至所有的结果 ，
     * 注意es的游标查询的是当下时刻的数据快照，
     * 即在游标查询之后的数据的变动不会影响游标查询的结果，
     * 默认游标查询根据_doc字段进行排序
     */
    @ApiOperation("游标查询文档")
    @GetMapping("cusor")
    public List<Blog> cusor() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.rangeQuery("serialNum").gte(1).lte(2));
        searchSourceBuilder.size(2);
        searchRequest.source(searchSourceBuilder);
        Scroll scroll = new Scroll(timeValueMillis(10L));
        /**
         *
         * 在搜索条件之后使用searchSourceBuilder.size(2)设置了每次游标只抽取2条数据，
         * 设置每次游标的超时时间是1毫秒timeValueMillis，可以适当调高超时时间防止由于超时还没查完导致游标提前结束。
         * 在执行游标的时候，第一次使用了客户端的search方法，从第二次开始使用scroll方法，
         * 每开始下一次游标的时候都通过查看本次游标的结果是否为空response.getHits().getHits()来判断是否还要继续，
         * 把每次游标的返回结果收集起来拿到全部数据
         *
         */
        searchRequest.scroll(scroll);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        String scrollId = response.getScrollId();
        SearchHit[] hits = response.getHits().getHits();
        List<SearchHit> resultSearchHit = new ArrayList<>();
        List<Blog> blogs = new ArrayList<>();
        while (hits != null && hits.length > 0) {
            System.out.println(hits.length);
            System.out.println(scrollId);
            resultSearchHit.addAll(Arrays.asList(hits));
            SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
            searchScrollRequest.scroll(scroll);
            SearchResponse searchScrollResponse = restHighLevelClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);
            if (response.status() == RestStatus.OK) {
                scrollId = searchScrollResponse.getScrollId();
                hits = searchScrollResponse.getHits().getHits();
                for (SearchHit searchHit : hits) {
                    String sourceAsString = searchHit.getSourceAsString();
                    Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                    blogs.add(blog);
                }
            } else {
                throw new Exception("es运行异常");
            }

        }


        // 清除滚屏
        if (scrollId != null) {
            ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
            clearScrollRequest.addScrollId(scrollId);
            ClearScrollResponse clearScrollResponse = restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
            boolean succeeded = clearScrollResponse.isSucceeded();
            if(!succeeded){
                throw new Exception("清除滚屏失败");
            }
        }


        return blogs;
    }


    @ApiOperation("范围查询文档")
    @GetMapping("range")
    public List<Blog> range() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.rangeQuery("serialNum").gte(1).lte(2));
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;
    }


    @ApiOperation("精确查询文档")
    @GetMapping("term")
    public List<Blog> term() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.termQuery("serialNum", "1"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }



    @ApiOperation("包含排除")
    @GetMapping("fetchSource")
    public List<Blog> fetchSource() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置源字段过虑,第一个参数结果集包括哪些字段，第二个参数表示结果集不包括哪些字段
        searchSourceBuilder .fetchSource(new String[]{"name","age","city","createTime"},new String[]{});
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }

    @ApiOperation("in")
    @GetMapping("in")
    public List<Blog> in(List<String> ids) throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.termsQuery("_id", ids));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }

    @ApiOperation("多精确查询文档")
    @GetMapping("terms")
    public List<Blog> terms() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.termsQuery("serialNum", "1", "2"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }

    @ApiOperation("深偏移总数")
    @GetMapping(" trackTotalHits")
    public long trackTotalHits() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");

        SearchSourceBuilder  searchSourceBuilder= new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        searchSourceBuilder.trackTotalHits(true);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        long total=0l;
        if (response.status() == RestStatus.OK) {
            // 满足条件的总记录数
            total = response.getHits().getTotalHits().value;
        } else {
            throw new Exception("es运行异常");
        }

        return total;


    }

    @ApiOperation("全部匹配查询文档")
    @GetMapping(" matchAll")
    public List<Blog> matchAll() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("匹配查询文档")
    @GetMapping("match")
    public List<Blog> match() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchQuery("title", "Spring Data ElasticSearch").operator(Operator.OR));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("多匹配查询文档")
    @GetMapping("multiMatch")
    public List<Blog> multiMatch() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.multiMatchQuery("2", "title", "content").operator(Operator.OR));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }

    @ApiOperation("短语查询文档")
    @GetMapping("matchPhrase")
    public List<Blog> matchPhrase() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.matchPhraseQuery("title", "Spring Data").slop(1));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("字符串查询文档")
    @GetMapping("queryString")
    public List<Blog> queryString() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.queryStringQuery("Spring Data").field("title"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("前缀查询文档")
    @GetMapping("prefix")
    public List<Blog> prefix() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.prefixQuery("content", "这"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("容错匹配查询文档")
    @GetMapping("fuzzy")
    public List<Blog> fuzzy() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.fuzzyQuery("title", "Sprrng"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }

    @ApiOperation("非null查询文档")
    @GetMapping("exists")
    public List<Blog> exists() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.existsQuery("title"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("通配符查询文档")
    @GetMapping("wildcard")
    public List<Blog> wildcard() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.wildcardQuery("title", "Spring*"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("正则查询文档")
    @GetMapping("regexp")
    public List<Blog> regexp() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.regexpQuery("title", "/^Spring/"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }

    @ApiOperation("提高查询文档")
    @GetMapping("boosting")
    public List<Blog> boosting() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.boostingQuery(
                        QueryBuilders.matchQuery("title", "Spring"),
                        QueryBuilders.matchQuery("title", "2")
                ).negativeBoost(0.5f)
        );
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("布尔查询文档")
    @GetMapping("bool")
    public List<Blog> bool() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("title", "Spring"))
                .should(QueryBuilders.termQuery("author", "Tom"))
                .should(QueryBuilders.termQuery("author", "Tony"))
        );
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("过滤查询文档")
    @GetMapping("filter")
    public List<Blog> filter() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.boolQuery()
                .filter(QueryBuilders.matchQuery("title", "Spring"))
        );
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("高亮查询文档")
    @GetMapping("highLight")
    public List<Blog> highLight() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.boolQuery()
                .filter(QueryBuilders.matchQuery("title", "Spring"))
        );
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title", 10)
                .preTags("<font color='red'>")
                .postTags("</font>");

        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);
        List<Blog> blogs = new ArrayList<>();
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            SearchHits hits = response.getHits();
            String[] attrs = new String[]{"title"};

            for (SearchHit searchHit : hits) {
                Blog blog = null;
                Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
                for (String field : attrs) {
                    HighlightField hField = highlightFields.get(field);
                    if (hField != null) {
                        //替换高亮字段
                        Text[] fragments = hField.fragments();
                        StringBuilder text = new StringBuilder();
                        for (Text textGet : fragments) {
                            text.append(textGet);
                        }
                        //对象的值只能读一次,否则会被覆盖
                        if (blog == null) {
                            //转换数据类型
                            blog = JSONUtil.toBean(searchHit.getSourceAsString(), Blog.class);
                        }
                        //设置对象的属性值
                        ReflectUtil.setFieldValue(blog, field, text.toString());
                        if (blog != null) {
                            blogs.add(blog);
                        }
                    }
                }

            }

        } else {
            throw new Exception("es运行异常");
        }


        return blogs;


    }


    @ApiOperation("脚本聚合查询文档")
    @GetMapping("script")
    public List<Map<String, String>> script() throws Exception {
        Script script = new Script("doc['status']");
//        CardinalityAggregationBuilder aggregationBuilder = AggregationBuilders.cardinality("user").script(script);
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("serialNum_serialNum").script(script);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.aggregation(aggregationBuilder);
        //不输出元素数据
        searchSourceBuilder.size(0);

        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("blog");
        searchRequest.source(searchSourceBuilder);
        log.debug("dsl:" + searchSourceBuilder.toString());

        List<Map<String, String>> result = new ArrayList<>();
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            Aggregations aggregations = response.getAggregations();
            //获取配置
            ParsedStringTerms parsedStringTerms = aggregations.get("serialNum_serialNum");
            List<? extends Terms.Bucket> buckets = parsedStringTerms.getBuckets();
            for (Terms.Bucket bucket : buckets) {
                //key的数据
                String key = bucket.getKey().toString();
                long docCount = bucket.getDocCount();
                Map<String, String> map = new HashMap<>();
                map.put(key, docCount + "");
                result.add(map);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return result;
    }

    @ApiOperation("聚合查询文档")
    @GetMapping("aggs")
    public SearchResponse aggs() throws Exception {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        /**
         * 使用tag字段进行桶分组
         * 使用sum、avg进行指标聚合
         */
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.
                terms("terms").field("category").                   //桶分组
                        subAggregation(AggregationBuilders.sum("sum").field("status")).  //求和
                        subAggregation(AggregationBuilders.cardinality("cardinality").field("status")).  //去重计数
                        subAggregation(AggregationBuilders.count("count").field("status")).  //计数
                        subAggregation(AggregationBuilders.extendedStats("extendedStats").field("status")).  //基本统计聚合
                        subAggregation(AggregationBuilders.stats("stats").field("status")).  //基本统计聚合
                        subAggregation(AggregationBuilders.percentiles("percentiles").field("status").percentiles(25, 50, 75, 100)).  //基本统计聚合
                        subAggregation(AggregationBuilders.range("range").field("status").addUnboundedTo(5).addRange(5, 10).addUnboundedFrom(10)).  //范围
                        subAggregation(AggregationBuilders.avg("avg").field("status")); //求平均值

        searchSourceBuilder.aggregation(aggregationBuilder);
        /**
         * 不输出原始数据
         */
        searchSourceBuilder.size(0);
        /**
         * 打印dsl语句
         */
        log.debug("dsl:" + searchSourceBuilder.toString());
        /**
         * 设置索引以及填充语句
         */
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("blog");
        searchRequest.source(searchSourceBuilder);
        ParsedStringTerms parsedStringTerms = null;
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
        } else {
            throw new Exception("es运行异常");
        }

        return response;
    }


    @ApiOperation("id查询文档")
    @GetMapping("id")
    public Blog id() throws Exception {
        GetRequest request = new GetRequest("blog", "1");
        GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
        String id = response.getId();
        String index = response.getIndex();
        System.out.println("response.getId() = " + id);
        System.out.println("response.getIndex() = " + index);
        if (response.isExists()) {
            long version = response.getVersion();
            System.out.println(version);
            String sourceAsString = response.getSourceAsString();
            Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
            return blog;
        } else {
            throw new Exception("文档不存在");
        }


    }

    @ApiOperation("id异步查询文档")
    @GetMapping("idAsync")
    public Blog idAsync() throws Exception {
        GetRequest request = new GetRequest("blog", "1");
        ActionListener<GetResponse> listener = new ActionListener<GetResponse>(){

            @Override
            public void onResponse(GetResponse response) {
                if (response.isExists()) {
                    long version = response.getVersion();
                    System.out.println(version);
                    String sourceAsString = response.getSourceAsString();
                    Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);

                } else {
                    throw new RuntimeException("文档不存在");
                }
            }

            @Override
            public void onFailure(Exception e) {
                throw new RuntimeException("查询失败");
            }
        };


        Cancellable async = restHighLevelClient.getAsync(request, RequestOptions.DEFAULT, listener);

        return null;

    }


    @ApiOperation("ids查询文档")
    @GetMapping("ids")
    public List<Blog> ids() throws Exception {
        SearchRequest searchRequest = new SearchRequest("blog");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.idsQuery().addIds("1", "2"));
        searchRequest.source(searchSourceBuilder);

        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        List<Blog> blogs = new ArrayList<>();
        if (response.status() == RestStatus.OK) {
            SearchHits searchHits = response.getHits();
            for (SearchHit searchHit : searchHits) {
                String sourceAsString = searchHit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }

        return blogs;


    }


    @ApiOperation("分页查询文档")
    @GetMapping("page")
    public Page<Blog> page() throws Exception {
        //创建搜索对象
        SearchRequest searchRequest = new SearchRequest("blog");
        //搜索构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        searchSourceBuilder.query(QueryBuilders.matchAllQuery())//执行查询条件
                .from(0)//起始条数
                .size(10)//每页展示记录
                .postFilter(QueryBuilders.matchAllQuery()) //过滤条件
                .sort("serialNum", SortOrder.DESC);//排序

        //创建搜索请求
        searchRequest.source(searchSourceBuilder);
        long total = 0;
        List<Blog> blogs = new ArrayList<Blog>();
        SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            total = response.getHits().getTotalHits().value;
            System.out.println("符合条件的文档总数: " + total);
            System.out.println("符合条件的文档最大得分: " + response.getHits().getMaxScore());
            SearchHits hits = response.getHits();
            for (SearchHit hit : hits) {
                String sourceAsString = hit.getSourceAsString();
                Blog blog = JSONUtil.toBean(sourceAsString, Blog.class);
                blogs.add(blog);
            }
        } else {
            throw new Exception("es运行异常");
        }


        return new PageImpl<Blog>(blogs, PageRequest.of(0, 10), total);
    }


    @ApiOperation("手动落盘")
    @GetMapping("refreshOrflush")
    public void refreshOrflush() throws Exception {
        RefreshRequest request = new RefreshRequest("blog");
        restHighLevelClient.indices().refresh(request, RequestOptions.DEFAULT);
        FlushRequest flushRequest = new FlushRequest("blog");
        restHighLevelClient.indices().flush(flushRequest, RequestOptions.DEFAULT);


    }


    @ApiOperation("新增或更新文档，如果索引不存在则创建")
    @GetMapping("index")
    public void index() throws Exception {


        User user1 = new User();
        user1.setId("1");
        user1.setParentId("0");
        user1.setFirst("John");
        user1.setSecond("Smith");
        user1.setAge(23);

        User user11 = new User();
        user11.setId("11");
        user11.setParentId("1");
        user11.setFirst("Alice");
        user11.setSecond("White");
        user11.setAge(24);


        User user12 = new User();
        user12.setId("12");
        user12.setParentId("1");
        user12.setFirst("John");
        user12.setSecond("Smith");
        user12.setAge(23);


        List<User> children = new ArrayList<>();
        children.add(user11);
        children.add(user12);
        user1.setChildren(children);

        String s = JSONUtil.toJsonStr(user1);


        // 1.构建一个 IndexRequest 请求，参数就是索引名称
        IndexRequest request = new IndexRequest("user");
        // 2.给请求配置一个 id，这个就是文档 id。如果指定了 id，相当于 put book/_doc/id ，也可以不指定 id，相当于 post book/_doc
        request.id(new Snowflake().nextIdStr());
        // 3.构建索引文本，有三种方式：JSON 字符串、Map 对象、XContentBuilder
        // 首先演示JSON
        request.source(s, XContentType.JSON);
        // 4.执行请求，同样有同步index和异步indexAsync两种方式

        //if do not set IMMEDIATE, last step will return nothing
        request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
        // 同步
        //新增或更新文档，如果索引不存在则创建
        IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);
        // 5.查看请求响应报文
        // 获取文档id
        String id = indexResponse.getId();
        System.out.println("id = " + id);
        // 获取索引名称
        String index = indexResponse.getIndex();
        System.out.println("index = " + index);
        // 判断文档是否添加成功
        if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
            System.out.println("文档添加成功");
        }
        // 判断文档是否更新成功（如果 id 已经存在）
        if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
            System.out.println("文档更新成功");
        }
        ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
        // 判断分片操作是否都成功
        if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
            System.out.println("有存在问题的分片");
        }
        // 有存在失败的分片
        if (shardInfo.getFailed() > 0) {
            for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
                System.out.println("failure.reason() = " + failure.reason());
            }
        }

        //异步
        /*client.indexAsync(request, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
            @Override
            public void onResponse(IndexResponse indexResponse) {

            }

            @Override
            public void onFailure(Exception e) {

            }
        });*/


    }


    @ApiOperation("批量新增文档")
    @GetMapping("bulkAdd")
    public <T> boolean bulkAdd() {
        try {
            BulkRequest bulkRequest = new BulkRequest();
            String json = "[\n" +
                    "        {\n" +
                    "            \"serialNum\": \"2\",\n" +
                    "            \"title\": \"Spring Data ElasticSearch学习教程2\",\n" +
                    "            \"content\": \"这是添加单个文档的实例2\",\n" +
                    "            \"author\": \"Tony\",\n" +
                    "            \"category\": \"ElasticSearch\",\n" +
                    "            \"status\": 1,\n" +
                    "            \"serialNum\": \"2\",\n" +
                    "            \"createTime\": \"2023-06-12 11:43:28\",\n" +
                    "            \"updateTime\": null,\n" +
                    "            \"coverImage\": null,\n" +
                    "            \"description\": null\n" +
                    "        },\n" +
                    "        {\n" +
                    "            \"serialNum\": \"1\",\n" +
                    "            \"title\": \"Spring Data ElasticSearch学习教程1\",\n" +
                    "            \"content\": \"这是添加单个文档的实例1\",\n" +
                    "            \"author\": \"Tony\",\n" +
                    "            \"category\": \"ElasticSearch\",\n" +
                    "            \"status\": 1,\n" +
                    "            \"serialNum\": \"1\",\n" +
                    "            \"createTime\": \"2023-06-12 11:43:28\",\n" +
                    "            \"updateTime\": null,\n" +
                    "            \"coverImage\": null,\n" +
                    "            \"description\": null\n" +
                    "        }\n" +
                    "    ]";
            JSONArray objects = JSONUtil.parseArray(json);
            List<Blog> blogs = objects.toList(Blog.class);


            for (int i = 0; i < blogs.size(); i++) {
                Blog entity = blogs.get(i);
                Long key = entity.getBlogId();
                entity.setBlogId(null);
                JSONConfig jsonConfig = new JSONConfig();
                jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
                String jsonValue = JSONUtil.toJsonStr(entity, jsonConfig);
                //可以是各种请求：crud
                IndexRequest indexRequest = new IndexRequest("blog");
                indexRequest.source(jsonValue, XContentType.JSON);
                indexRequest.id(key.toString());
                bulkRequest.add(indexRequest);
            }
            //设置超时
            bulkRequest.timeout("10s");
            BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            if (bulkResponse.status() == RestStatus.OK) {
                return true;
            } else {
                throw new Exception("es运行异常");
            }

        } catch (Exception e) {
            return false;
        }
    }


    @ApiOperation("批量嵌套新增文档")
    @GetMapping("bulkAddNested")
    public <T> boolean bulkAddNested() {
        try {
            BulkRequest bulkRequest = new BulkRequest();

            List<User> users = new ArrayList<>();
            User user1 = new User();
            user1.setId("1");
            user1.setParentId("0");
            user1.setFirst("John");
            user1.setSecond("Smith");
            user1.setAge(23);

            User user11 = new User();
            user11.setId("11");
            user11.setParentId("1");
            user11.setFirst("Alice");
            user11.setSecond("White");
            user11.setAge(24);


            User user12 = new User();
            user12.setId("12");
            user12.setParentId("1");
            user12.setFirst("John");
            user12.setSecond("Smith");
            user12.setAge(23);


            List<User> children1 = new ArrayList<>();
            children1.add(user11);
            children1.add(user12);
            user1.setChildren(children1);
            users.add(user1);


            User user2 = new User();
            user2.setId("2");
            user2.setParentId("0");
            user2.setFirst("John");
            user2.setSecond("Tom");
            user2.setAge(23);

            User user21 = new User();
            user21.setId("11");
            user21.setParentId("1");
            user21.setFirst("Alice");
            user21.setSecond("Black");
            user21.setAge(24);


            User user22 = new User();
            user22.setId("12");
            user22.setParentId("1");
            user22.setFirst("John");
            user22.setSecond("Smith");
            user22.setAge(23);


            List<User> children2 = new ArrayList<>();
            children2.add(user11);
            children2.add(user12);
            user2.setChildren(children2);
            users.add(user2);


            for (int i = 0; i < users.size(); i++) {
                User entity = users.get(i);
                String key = entity.getId();
                entity.setId(null);
                JSONConfig jsonConfig = new JSONConfig();
                jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
                String jsonValue = JSONUtil.toJsonStr(entity, jsonConfig);
                //可以是各种请求：crud
                IndexRequest indexRequest = new IndexRequest("user");
                indexRequest.source(jsonValue, XContentType.JSON);
                indexRequest.id(key);
                bulkRequest.add(indexRequest);
            }
            //设置超时
            bulkRequest.timeout("10s");
            BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            if (bulkResponse.status() == RestStatus.OK) {
                return true;
            } else {
                throw new Exception("es运行异常");
            }

        } catch (Exception e) {
            return false;
        }
    }


    @ApiOperation("批量删除文档")
    @GetMapping("bulkDelete")
    public <T> boolean bulkDelete() {
        try {
            BulkRequest bulkRequest = new BulkRequest();
            List<String> idList = new ArrayList<>();
            idList.add("1");
            idList.add("2");
            idList.forEach(item -> bulkRequest.add(new DeleteRequest("blog", item)));
            //设置超时
            bulkRequest.timeout("10s");
            BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            if (bulkResponse.status() == RestStatus.OK) {
                return true;
            } else {
                throw new Exception("es运行异常");
            }

        } catch (Exception e) {
            return false;
        }
    }


    @ApiOperation("删除文档")
    @GetMapping("delete")
    public void delete() throws Exception {
        DeleteRequest request = new DeleteRequest("book", "99");
        DeleteResponse response = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            System.out.println("response.getId() = " + response.getId());
            System.out.println("response.getIndex() = " + response.getIndex());
            System.out.println("response.getVersion() = " + response.getVersion());
            ReplicationResponse.ShardInfo shardInfo = response.getShardInfo();
            if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
                System.out.println("有分片存在问题");
            }
            if (shardInfo.getFailed() > 0) {
                for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
                    System.out.println("failure.reason() = " + failure.reason());
                }
            }

        } else {
            throw new Exception("es运行异常");
        }


    }

    @ApiOperation("条件删除文档")
    @GetMapping("deleteByQuery")
    public void deleteByQuery() throws Exception {
        DeleteByQueryRequest request = new DeleteByQueryRequest("blog");
        request.setQuery(QueryBuilders.rangeQuery("serialNum").lt(4));

        BulkByScrollResponse response = restHighLevelClient.deleteByQuery(request, RequestOptions.DEFAULT);
        if (response.getStatus().getSliceStatuses().size() == 0) {
            System.out.println(response.toString());
        } else {
            throw new Exception("es运行异常");
        }
    }


    @ApiOperation("更新文档")
    @GetMapping("update")
    public void update() throws Exception {
        UpdateRequest request = new UpdateRequest("blog", "1");
        // 通过脚本更新
        Map<String, Object> params = Collections.singletonMap("title", "三国演义666");
        Script script = new Script(ScriptType.INLINE, "painless", "ctx._source.name=params.name", params);
        request.script(script);
        // 通过json更新
        //request.doc("{\"name\": \"三国演义\"}", XContentType.JSON);
        // 通过Map更新
        //Map<String, Object> docMap = new HashMap<>();
        //docMap.put("name", "三国演义888");
        //request.doc(docMap);
        // 通过XContentBuilder更新
        //XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
        //jsonBuilder.startObject();
        //jsonBuilder.field("name", "三国演义666");
        //jsonBuilder.endObject();
        //request.doc(jsonBuilder);

        UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            System.out.println("response.getId() = " + response.getId());
            System.out.println("response.getIndex() = " + response.getIndex());
            System.out.println("response.getVersion() = " + response.getVersion());
            if (response.getResult() == DocWriteResponse.Result.UPDATED) {
                System.out.println("更新成功!");
            }
        } else {
            throw new Exception("es运行异常");
        }


    }


    @ApiOperation("条件更新文档")
    @GetMapping("updateByQuery")
    public void updateByQuery() throws Exception {
        UpdateByQueryRequest request = new UpdateByQueryRequest("blog");
        //通过查询 指定要更新的_id,条件要命中一个id，不能命中多个id
        request.setQuery(QueryBuilders.termQuery("serialNum", "1"));
        // 通过脚本更新
        Map<String, Object> params = Collections.singletonMap("title", "三国演义666");
        Script s = new Script(ScriptType.INLINE, "painless", "ctx._source.title=params.title", params);
        request.setScript(s);
        // 通过json更新
        //request.doc("{\"name\": \"三国演义\"}", XContentType.JSON);
        // 通过Map更新
        //Map<String, Object> docMap = new HashMap<>();
        //docMap.put("name", "三国演义888");
        //request.doc(docMap);
        // 通过XContentBuilder更新
        //XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
        //jsonBuilder.startObject();
        //jsonBuilder.field("name", "三国演义666");
        //jsonBuilder.endObject();
        //request.doc(jsonBuilder);

        BulkByScrollResponse response = restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
        if (response.getStatus().getSliceStatuses().size() == 0) {
            System.out.println(response.toString());
        } else {
            throw new Exception("es运行异常");
        }


    }

    @ApiOperation("条件嵌套更新文档")
    @GetMapping("updateNestedByQuery")
    public void updateNestedByQuery() throws Exception {
        UpdateByQueryRequest request = new UpdateByQueryRequest("user");
        //通过查询 指定要更新的_id,条件要命中一个id，不能命中多个id
        request.setQuery( QueryBuilders.matchQuery("second", "Smith"));
        // 通过脚本更新
        User user13 = new User();
        user13.setId("13");
        user13.setParentId("1");
        user13.setFirst("John");
        user13.setSecond("Ben");
        user13.setAge(23);
        Map<String, Object> params = new HashMap<>();
        params.put("u", BeanUtil.beanToMap(user13));
        Script s = new Script(ScriptType.INLINE, "painless", "ctx._source.children.add(params.u)", params);
        request.setScript(s);
        // 通过json更新
        //request.doc("{\"name\": \"三国演义\"}", XContentType.JSON);
        // 通过Map更新
        //Map<String, Object> docMap = new HashMap<>();
        //docMap.put("name", "三国演义888");
        //request.doc(docMap);
        // 通过XContentBuilder更新
        //XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
        //jsonBuilder.startObject();
        //jsonBuilder.field("name", "三国演义666");
        //jsonBuilder.endObject();
        //request.doc(jsonBuilder);

        BulkByScrollResponse response = restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
        if (response.getStatus().getSliceStatuses().size() == 0) {
            System.out.println(response.toString());
        } else {
            throw new Exception("es运行异常");
        }


    }


    @ApiOperation("新增或更新文档")
    @GetMapping("indexOrupdate")
    public void indexOrupdate() throws Exception {
        UpdateRequest request = new UpdateRequest("blog", "2");
        // 通过XContentBuilder更新
        XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
        jsonBuilder.startObject();
        jsonBuilder.field("title", "三国演义666");
        jsonBuilder.endObject();
        request.doc(jsonBuilder);
        request.upsert("{\"title\": \"红楼梦\",\"author\": \"曹雪芹\"}", XContentType.JSON);
        UpdateResponse response = restHighLevelClient.update(request, RequestOptions.DEFAULT);
        if (response.status() == RestStatus.OK) {
            System.out.println("response.getId() = " + response.getId());
            System.out.println("response.getIndex() = " + response.getIndex());
            System.out.println("response.getVersion() = " + response.getVersion());
            if (response.getResult() == DocWriteResponse.Result.UPDATED) {
                System.out.println("更新成功!");
            }

        } else {
            throw new Exception("es运行异常");
        }


    }


}
